package com.lwq.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.lwq.entity.Member;
import com.lwq.entity.Permission;
import com.lwq.entity.Role;
import com.lwq.mapper.MemberMapper;
import com.lwq.mapper.PermissionMapper;
import com.lwq.mapper.RoleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.*;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author lwq
 * <p>负责重写登录逻辑的类 必须实现 `UserDetailsService` 接口并重写 `loadUserByUsername()` 方法 </p>
 */

@Service
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 重写的登录逻辑
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        // 按账号获取会员信息
        Member member = this.selectByUsername(username);

        // 获取会员表主键
        Integer memberId = member.getMemberId();

        // 按会员主键获取会员全部角色
        List<Role> roles = roleMapper.selectRolesByMemberId(memberId);

        // 按会员主键获取会员全部权限
        List<Permission> permissions = permissionMapper.selectPermissionsByMemberId(memberId);

        // 使用BCRYPT将会员密码进行加密
        String password = passwordEncoder.encode(member.getPassword());

        // 准备authorities权限集合: 添加会员的全部权限名和角色名
        Set<GrantedAuthority> authorities = new HashSet<>();
        roles.forEach(role ->
                // SpringSecurity要求每个角色名都添加 `ROLE_` 前缀
                authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleTitle())));
        permissions.forEach(permission ->
                authorities.add(new SimpleGrantedAuthority(permission.getPermissionTitle())));
        System.out.println("authorities: " + authorities);

        // org.springframework.security.core.userdetails.User
        return new User(username, password, authorities);
    }

    /**
     * 通过账号获取会员信息（包括角色和权限）
     *
     * @param username 账号
     * @return 会员信息
     */
    private Member selectByUsername(String username) {
        // 按账号从数据库中查询出指定会员信息
        QueryWrapper<Member> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        Member member = memberMapper.selectOne(queryWrapper);
        if (null == member) {
            throw new UsernameNotFoundException("账号不存在");
        }
        return member;
    }
}
